﻿using Common;
using Microsoft.Extensions.Options;
using StackExchange.Redis;

namespace BaseRepository.Redis;

public class RedisRepository : IRedisRepository
{
    /// <summary>
    /// redis的仓储  封装redis的一些基本的用法  明天在docker里面装redis  然后再写一个封装redis的操作类  周末就开始写前端了
    /// </summary>

    protected readonly IDatabase _database;

    protected readonly ConnectionMultiplexer _connectionMultiplexer;
    // 可以通过依赖注入的方式  获取  也可以直接通过静态方法的方式获取 redis的连接实例
    public RedisRepository(ConnectionMultiplexer connectionMultiplexer)
    {
        var redisConfig = Appsettings.app<RedisConfig>("Redis");
        ArgumentNullException.ThrowIfNull(redisConfig);
        this._connectionMultiplexer =
           connectionMultiplexer ?? throw new ArgumentNullException(nameof(connectionMultiplexer));
        // 获取redis的database  redis直接单例一直开着连接就好了  使用exchange.redis这个库的话
        this._database = connectionMultiplexer.GetDatabase(redisConfig.DataBase);
    }
    /// <summary>
    /// 判断是否存在
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public Task<bool> Exist(string key)
    {
        ArgumentException.ThrowIfNullOrEmpty(key);
        return this._database.KeyExistsAsync(key);
    }
    /// <summary>
    /// 删除一个key
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public Task Remove(string key)
    {
        ArgumentException.ThrowIfNullOrEmpty(key);
        return this._database.KeyDeleteAsync(key);
    }
    /// <summary>
    /// 获取key的value
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="key"></param>
    /// <returns></returns>
    public async Task<TEntity?> StringGet<TEntity>(string key)
    {
        ArgumentException.ThrowIfNullOrEmpty(key);
        var value = await this._database.StringGetAsync(key);
        if (value.HasValue&&!value.IsNullOrEmpty)
        {
            return JsonHelper.DeserializeObject<TEntity>(value);
        }

        return default;
    }
    /// <summary>
    /// 获取多个key的value
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="keys"></param>
    /// <returns></returns>
    public async Task<List<TEntity?>> StringGet<TEntity>(string[] keys)
    {
        ArgumentNullException.ThrowIfNull(keys);
        var redisKeys = new List<RedisKey>();
        foreach (var key in keys)
        {
            redisKeys.Add(key);
        }
        var values = await this._database.StringGetAsync(redisKeys.ToArray());
        return values.Select(p =>
        {
            if (p.HasValue&&!p.IsNullOrEmpty)
            {
                return JsonHelper.DeserializeObject<TEntity>(p);
            }

            return default(TEntity);
        }).ToList();
    }
    /// <summary>
    /// 设置redis key value
    /// </summary>
    /// <param name="key"></param>
    /// <param name="value"></param>
    /// <param name="cacheTime"></param>
    /// <returns></returns>
    public  Task<bool> StringSet(string key, object? value, TimeSpan? cacheTime = null)
    {
        ArgumentException.ThrowIfNullOrEmpty(key);
        ArgumentNullException.ThrowIfNull(value);
        //var redisValue = value ?? "";
        if (value is string cacheValue)
        {
           return this._database.StringSetAsync(key, cacheValue,cacheTime);
        }
        return this._database.StringSetAsync(key, JsonHelper.SerializeObject(value),cacheTime);
    }

    /// <summary>
    /// 多个一起设置redis
    /// </summary>
    /// <param name="keyValues"></param>
    /// <param name="cacheTime"></param>
    /// <returns></returns>
    public  Task<bool> StringSet(Dictionary<string, object> keyValues, TimeSpan? cacheTime =null)
    {
        ArgumentNullException.ThrowIfNull(keyValues);
        var keyValuePairs = new List<KeyValuePair<RedisKey, RedisValue>>();
        foreach (var item in keyValues)
        {
            var itemValue = "";
            if (item.Value is string cacheValue)
            {
                itemValue = item.Value.ToString();
            }
            else
            {
                itemValue = JsonHelper.SerializeObject(item.Value);
            }
            keyValuePairs.Add(new KeyValuePair<RedisKey, RedisValue>(item.Key,itemValue));
        }

        return this._database.StringSetAsync(keyValuePairs.ToArray());
    }




}